//edit
//`ifndef isVIVADO
//`include "env.v"
//`endif
 
module debugger_ch341a (
    input           clk,
    input           clk_50M,
    input           reset_n,
    
    //external
    output reg      ch341a_ack,//debug模块请求置1，cs0拉低置0
    output          ch341a_miso,//data out
    input           ch341a_mosi,
    input           ch341a_sck,
    input           ch341a_cs2,//addr in
    input           ch341a_cs1,//data in
    input           ch341a_cs0,//cmd in /data out

    
    
    
    
    `ifdef isVIVADO
    output        HP0_clk,
    output [31:0] HP0_araddr  ,
    output  [1:0] HP0_arburst ,
    output [ 3:0] HP0_arlen   ,
    input         HP0_arready ,
    output reg    HP0_arvalid ,
    output [31:0] HP0_awaddr  ,
    output [ 1:0] HP0_awburst ,
    output [ 3:0] HP0_awlen   ,
    input         HP0_awready ,
    output reg    HP0_awvalid ,
    output reg    HP0_bready  ,
    input         HP0_bvalid  ,
    input  [31:0] HP0_rdata   ,
    output reg    HP0_rready  ,
    input         HP0_rvalid  ,
    output [31:0] HP0_wdata   ,
    output reg    HP0_wlast   ,
    input         HP0_wready  ,
    output [ 3:0] HP0_wstrb   ,
    output reg    HP0_wvalid  ,

//output [31:0] HP0_awaddr,
//output [3:0]  HP0_awlen,
//output [2:0]  HP0_awsize,
//output [1:0]  HP0_awburst,
//output reg    HP0_awvalid,
//input         HP0_awready,
//
//output [31:0] HP0_araddr,
//output [3:0]  HP0_arlen,
//output [2:0]  HP0_arsize,
//output [1:0]  HP0_arburst,
//output reg    HP0_arvalid,
//input         HP0_arready,
//
// 
//input [31:0]  HP0_rdata,
//input [1:0]   HP0_rresp,
//input         HP0_rlast,
//input         HP0_rvalid,
//output reg    HP0_rready,
//    
//output     [31:0] HP0_wdata,
//output     [3:0]  HP0_wstrb,
//output reg        HP0_wlast,
//output reg        HP0_wvalid,
//input             HP0_wready,
// 
//input  [1:0]      HP0_bresp,
//input             HP0_bvalid,
//output reg        HP0_bready,
`endif

    
    //cpu
    output reg          debug_reset_n,
    output reg          halt_debug,
    output reg          debug_step,
    input               halt_cpu,
    input        [31:0] curr_data,
    input        [31:0] pcResult,
    input        [31:0] private_offset,
    input        [31:0] private_offset_rear,
    input        [31:0] pc,
    input        [31:0] cpu_address,
    input               irq_enable,
    input        [31:0] irq_addr,

    output reg          debug_read,
    output reg          debug_write,
    output reg          debug_read_ins,
    output reg  [31:0]  debug_address,
    output reg  [31:0]  debug_writedata,
    output reg   [3:0]  debug_byteenable,
    input       [31:0]  avm_m0_address,
    input               avm_m0_read,
    input               avm_m0_write,
    input       [31:0]  avm_m0_readdata,
    input               avm_m0_waitrequest,
    input               avm_m1_read,
    input       [31:0]  avm_m1_readdata,
    input               avm_m1_waitrequest,
    input               irq_req,

    output              debug_clk,
    output       [8:0]  debug_regAddr,
    input       [31:0]  debug_regData,
    output              debug_regWriteEna,
    output      [31:0]  debug_regWriteData,

    output        [7:0] pc_record_index_read,
    input        [31:0] pc_record_data,
    input         [7:0] pc_record_index,
    
    output        [7:0] debug_stash_index_read,
    input        [31:0] debug_stash_data,
    input         [7:0] debug_stash_index,

    //spirom
    output reg        spirom_debug_read_req     ,
    input             spirom_debug_read_ack     ,
    input       [7:0] spirom_debug_read_data    ,
    output reg        spirom_debug_write_req    ,
    input             spirom_debug_write_ack    ,
    output reg  [7:0] spirom_debug_write_data   ,
    output reg        spirom_debug_cs           ,

    //cache
    output reg        debug_nocache,
    input      [31:0] free_cache_timer,
    output reg  [4:0] cache_debug_index ,
    input      [31:0] cache_debug_data ,
    input      [31:0] cache_debugIns_data ,
    input      [31:0] cache_config,
    input      [31:0] flushCount,
    input      [31:0] glichCount,
    input      [31:0] glichCountIns,

    //vga
    output reg        vga_control_by_debugger,
    output reg        vga_debugger_read_line_req,
    output            vga_debugger_read_line_A_B,
    input             vga_debugger_read_line_ack,
    output reg [15:0] vga_debugger_read_line_addr,
    output      [9:0] vga_debugger_read_pixel_addr,
    output            vga_debugger_read_pixel_clk,
    input      [15:0] vga_debugger_read_pixelA_data,
    input      [15:0] vga_debugger_read_pixelB_data,

    output reg [31:0] debug_hid,
    output reg        debug_hid_req,

    //misc
    input       [7:0] debugin8,
    input      [31:0] debugin32,
    output reg        debug_flg,
    input      [31:0] debug_tx_to_pc,
    input             debug_tx_to_pc_valid,
    output reg        debug_tx_to_pc_read,
    output reg [31:0] debug_rx_from_pc,
    output reg        debug_rx_from_pc_valid,
    input             debug_rx_from_pc_read,
    output reg [31:0] debug_vga_base_addr,
    
    input dummy
);
  assign vga_debugger_read_line_A_B = 1;//a

  assign pc_record_index_read = data[7:0];
  assign debug_stash_index_read = data[7:0];

  reg [31:0] accessTime;
  reg        accessTimeCnt;
  reg        accessTimeCntLast;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      accessTime <= 0;
      accessTimeCnt <= 0;
      accessTimeCntLast <= 0;
    end else begin
      accessTimeCntLast <= accessTimeCnt;
      if(avm_m0_write || avm_m0_read || avm_m1_read)begin
        accessTimeCnt <= 1;
      end else begin
        accessTimeCnt <= 0;
      end
      if(accessTimeCnt)begin
        if(!accessTimeCntLast)begin
          accessTime <= 0;
        end else begin
          accessTime <= accessTime + 1'b1;
        end
      end
    end
  end
  
  assign debug_clk = clk;
`ifdef isVIVADO
  assign HP0_clk = clk;
`endif
  
  reg   [2:0] debug_readmem_step;

  reg  [31:0] debug_data_out;
  reg         debug_data_send;

  //https://www.intel.cn/content/www/cn/zh/programmable/products/processors/support.html

  reg command_ack;


  reg spirom_debug_read_ack_buff;
  reg spirom_debug_write_ack_buff;
  reg flash_debug_read_ack_buff;
  reg flash_debug_write_ack_buff;


`ifdef isALTERA
  altsource_probe	prob0 (
        .probe (debug_address),
        .source ()
        );
  defparam
    prob0.enable_metastability = "NO",
    prob0.instance_id = "P0",
    prob0.probe_width = 32,
    prob0.sld_auto_instance_index = "YES",
    prob0.sld_instance_index = 0,
    prob0.source_initial_value = " 0",
    prob0.source_width = 32;
  
  altsource_probe	prob1 (
        .probe ({
          debug_write,        //10
          debug_read,         //9
          debug_memcpy_step,  //87
          command_req,        //6
          command_ack,        //5
          avm_m0_write,       //4
          avm_m0_read,        //3
          avm_m1_read,        //2
          avm_m1_waitrequest, //1
          avm_m0_waitrequest  //0
        }),
        .source ()
        );
  defparam
    prob1.enable_metastability = "NO",
    prob1.instance_id = "P1",
    prob1.probe_width = 32,
    prob1.sld_auto_instance_index = "YES",
    prob1.sld_instance_index = 0,
    prob1.source_initial_value = " 0",
    prob1.source_width = 32;
`endif

`ifdef isVIVADO
//wire [1:0] prob3 = {ch341a_ack,debug_data_send};
//vio_0 vio_0_inst (
//.clk(clk),
//.probe_in0(command),
//.probe_in1(debug_writedata),
//.probe_in2(ch341a_cs0),
//.probe_in3(prob3),
//.probe_in4(tempclk)
//);
  assign HP0_wstrb = debug_byteenable;
  assign HP0_wdata = debug_writedata;
  assign HP0_awaddr = debug_address;
  assign HP0_awlen = 0;
  assign HP0_araddr = debug_address;
  assign HP0_arlen = 0;
  assign HP0_arburst = 0;
  assign HP0_awburst = 0;

`endif

  assign ch341a_miso = !ch341a_cs0 ? ch341a_miso0 : ch341a_miso2;

  //增加一个起始地址寄存器
  
  //传输完成后，启动前要把寄存器清零，特别是r0
  //ch341a_cs2 作为单读
  //222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
  assign debug_regAddr = (
                          (!ch341a_cs2) ? 
                            ch341a_cs2_index[13:5] : 
                            (
                              (!ch341a_cs1)?
                                ch341a_cs1_index_temp[13:5] :
                                debug_regAddr_wire
                            )
                         );//[8:0]  +transferBaseAddr

  assign vga_debugger_read_pixel_addr = ch341a_cs2_index[13:4];
  assign vga_debugger_read_pixel_clk = ~ch341a_sck;
  //ch341a_cs2 作为单读到PC
  wire ch341a_miso2 = vga_control_by_debugger ? vga_debugger_read_pixelA_data[ch341a_cs2_index[3:0]] : debug_regData[ch341a_cs2_index[4:0]];
  reg [13:0] ch341a_cs2_index;//9+5 512*32 bit , 10+4 1024*16 bit
  always @(negedge ch341a_sck or posedge ch341a_cs2) begin
    if(ch341a_cs2)begin
      ch341a_cs2_index <= 0;
    end else begin
      ch341a_cs2_index <= ch341a_cs2_index + 1'b1;
    end
  end

  
  
  //1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
  //ch341a_cs1 作为单写从PC
  assign debug_regWriteData = (!ch341a_cs1) ? debug_regWriteData_ch341a_cs1_buff : debug_writedata;
  wire [13:0] ch341a_cs1_index_temp = ch341a_cs1_index - 1'b1;//9+5 512*32 bit
  reg [13:0] ch341a_cs1_index;//9+5 512*32 bit
  reg [31:0] debug_regWriteData_ch341a_cs1_buff;
  reg        debug_regWriteEna_ch341a_cs1_buff;
  always @(posedge ch341a_sck or posedge ch341a_cs1) begin
    if(ch341a_cs1)begin
      ch341a_cs1_index <= 0;
    end else begin
      ch341a_cs1_index <= ch341a_cs1_index + 1'b1;
      debug_regWriteEna_ch341a_cs1_buff <= 0;
      if(ch341a_cs1_index[4:0]==5'b11111)begin
        debug_regWriteEna_ch341a_cs1_buff <= 1;
      end
      debug_regWriteData_ch341a_cs1_buff[ch341a_cs1_index[4:0]] <= ch341a_mosi;
    end
  end
  
  assign debug_regWriteEna = (!ch341a_cs1) ? debug_regWriteEna_ch341a_cs1 : debug_regWriteEna_reg;
  reg debug_regWriteEna_ch341a_cs1;
  reg debug_regWriteEna_ch341a_cs1_buff1;
  reg debug_regWriteEna_ch341a_cs1_buff2;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      debug_regWriteEna_ch341a_cs1 <= 0;
      debug_regWriteEna_ch341a_cs1_buff1 <= 0;
      debug_regWriteEna_ch341a_cs1_buff2 <= 0;
    end else begin
      debug_regWriteEna_ch341a_cs1_buff1 <= debug_regWriteEna_ch341a_cs1_buff;
      debug_regWriteEna_ch341a_cs1_buff2 <= debug_regWriteEna_ch341a_cs1_buff1;

      debug_regWriteEna_ch341a_cs1 <= 0;
      if(!debug_regWriteEna_ch341a_cs1_buff2 && debug_regWriteEna_ch341a_cs1_buff1)begin //上升沿触发写入
        debug_regWriteEna_ch341a_cs1 <= 1;
      end
    end
  end
  
  reg [31:0] tempclk;
    always @(posedge clk or negedge reset_n) begin
    if(!reset_n)begin
      tempclk <= 0;
    end else begin
      if(!ch341a_cs0)begin
        tempclk <= tempclk + 1'b1;
      end
    end
  end
  


  //00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  //输出，32bit，ack 上升时锁存
  reg [31:0] ch341a_data_out_buff;//out data
  reg ch341a_miso0;
  always @(posedge ch341a_sck or posedge ch341a_ack) begin
    if (ch341a_ack) begin//ack拉高时锁存
      ch341a_miso0 <= 0;
      ch341a_data_out_buff <= debug_data_out;
    end else begin
      if(!ch341a_cs0) begin
        ch341a_miso0 <= ch341a_data_out_buff[0];
        ch341a_data_out_buff[30:0] <= ch341a_data_out_buff[31:1];
      end
    end
  end

  //debug_data_send(防止当ch341a_ack_set为1时，ch341a_cs0拉低，则输出，外部判断ch341a_ack_set是否为1，仅当ch341a_ack==1 && debug_data_send==0 时才发送ch341a_cs0==0)
  //always @(posedge debug_data_send or negedge ch341a_cs0 or negedge reset_n) begin
  //  if(!reset_n) begin
  //    ch341a_ack <= 1'b0;
  //  end else begin
  //    if (debug_data_send) begin
  //      ch341a_ack <= 1'b1;
  //    end else if (!ch341a_cs0)begin
  //      ch341a_ack <= 1'b0;
  //    end
  //  end
  //end
  always @(posedge clk or negedge reset_n) begin
    if(!reset_n) begin
      ch341a_ack <= 1'b0;
    end else begin
      if(debug_data_send)begin
        ch341a_ack <= 1'b1;
      end 
      if (!ch341a_cs0)begin
        ch341a_ack <= 1'b0;
      end
    end
  end
  
  //5个字节指令加数据
  wire [7:0] command = ch341a_cmd_data[7:0];
  wire [31:0] data = ch341a_cmd_data[39:8];
  reg [39:0] ch341a_cmd_data;
  always @(posedge ch341a_sck) begin
    if(!ch341a_cs0)begin
      ch341a_cmd_data <= {ch341a_mosi, ch341a_cmd_data[39:1]};
    end
  end

  reg ch341a_cs0_buff;//新
  reg ch341a_cs0_buff2;//旧
  reg command_req;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin
      ch341a_cs0_buff <= 1;
      ch341a_cs0_buff2 <= 1;
      command_req <= 0;
    end else begin
      ch341a_cs0_buff <= ch341a_cs0;
      ch341a_cs0_buff2 <= ch341a_cs0_buff;
      
      if(!ch341a_cs0_buff2 && ch341a_cs0_buff)begin //上升沿触发debug指令
        command_req <= 1;
      end
      
      if(command_ack)begin
        command_req <= 0;
      end
    end
  end

  reg [1:0] debug_readmem_ar_status;
  reg [1:0] debug_readmem_dr_status;
  reg [1:0] debug_readmem_aw_status;
  reg [1:0] debug_readmem_dw_status;
  reg [1:0] debug_readmem_b_status ;
  parameter STATUS_INIT = 0;
  parameter STATUS_WAIT = 1;
  parameter STATUS_FINISH = 2;

  reg [31:0] read1_time;
  reg [31:0] read2_time;
  reg [31:0] write1_time;
  reg [31:0] write2_time;
  reg [31:0] write3_time;

  wire [8:0] debug_regAddr_wire = debug_address[10:2];
  
  reg debug_regWriteEna_reg;
  //reg [8:0] transferBaseAddr;
  reg [1:0] debug_memcpy_step;
  reg [2:0] debug_spirom_send4_index;
  reg vga_debugger_read_line_ack_buff;
  always @(posedge clk or negedge reset_n) begin
    if (!reset_n) begin

      command_ack <= 0;
      debug_step<=0;
      debug_readmem_step<=0;

      halt_debug<=1;
      debug_read<=0;
      debug_write<=0;
      debug_read_ins<=0;
      debug_reset_n<=1;
      debug_byteenable <= 4'b1111;
      //accessTime <= 0;
      //uart_send_ack_buff<=0;
      
      spirom_debug_read_req<=0;
      spirom_debug_write_req<=0;
      spirom_debug_write_data<=0;
      spirom_debug_cs <= 0;
      spirom_debug_read_ack_buff <= 0;
      spirom_debug_write_ack_buff <= 0;
      
      debug_address <= 0;
      debug_writedata <= 0;
      
      debug_nocache <= 0;
      cache_debug_index <= 0;

      //debug_req_temp_reset<=0;
      //debug_ack_req<=0;
      debug_data_out<=0;
      
      //transferBaseAddr<= 0;
      debug_memcpy_step <= 0;
      debug_regWriteEna_reg <= 0;
      debug_spirom_send4_index <= 0;
      
      debug_flg <= 0;

      vga_control_by_debugger <= 0;
      vga_debugger_read_line_req <= 0;
      vga_debugger_read_line_ack_buff <= 0;

      debug_hid <= 0;
      debug_hid_req <= 0;


`ifdef isVIVADO
      debug_readmem_ar_status <= 0;
      debug_readmem_dr_status <= 0;
      debug_readmem_aw_status <= 0;
      debug_readmem_dw_status <= 0;
      debug_readmem_b_status  <= 0;

      HP0_arvalid <= 0;
      HP0_rready <= 0;
      
      HP0_awvalid <= 0;
      HP0_wvalid <= 0;
      HP0_bready <= 0;

      read1_time <= 0;
      read2_time <= 0;
      write1_time <= 0;
      write2_time <= 0;
      write3_time <= 0;
`endif


    end else begin

      spirom_debug_read_ack_buff <=  spirom_debug_read_ack;
      spirom_debug_write_ack_buff <= spirom_debug_write_ack;
      vga_debugger_read_line_ack_buff <= vga_debugger_read_line_ack;
      
      debug_data_send <= 0;

      if(command_req && !command_ack) begin//command_ack==0
        case(command[6:0])
        8'h00 : begin command_ack<=1; end

`ifdef isVIVADO
        //read
        8'h05: begin
          if         (debug_readmem_ar_status==STATUS_INIT)begin
            HP0_arvalid <= 1;
            read1_time <= 0;
            if(HP0_arready)begin
              debug_readmem_ar_status <= STATUS_FINISH;
            end else begin
              debug_readmem_ar_status <= STATUS_WAIT;
            end
          end else if(debug_readmem_ar_status==STATUS_WAIT)begin
              read1_time <= read1_time + 1'b1;
            if(HP0_arready)begin
              debug_readmem_ar_status <= STATUS_FINISH;
            end
          end else if(debug_readmem_ar_status==STATUS_FINISH)begin
            HP0_arvalid <= 0;
          end
          
          if         (debug_readmem_dr_status==STATUS_INIT)begin
            HP0_rready <= 1;
            read2_time <= 0;
            if(HP0_rvalid)begin
              debug_data_out <= HP0_rdata;
              debug_readmem_dr_status <= STATUS_FINISH;
            end else begin
              debug_readmem_dr_status <= STATUS_WAIT;
            end
          end else if(debug_readmem_dr_status==STATUS_WAIT)begin
            read2_time <= read2_time + 1'b1;
            if(HP0_rvalid)begin
              debug_data_out <= HP0_rdata;
              debug_readmem_dr_status <= STATUS_FINISH;
            end
          end else if(debug_readmem_dr_status==STATUS_FINISH)begin
            HP0_rready <= 0;
          end
          
          if(debug_readmem_ar_status==STATUS_FINISH && debug_readmem_dr_status==STATUS_FINISH)begin
            command_ack = 1;
            debug_data_send<=1;
            debug_readmem_ar_status <= STATUS_INIT;
            debug_readmem_dr_status <= STATUS_INIT;
          end

        end
        //write
        8'h06: begin
          if         (debug_readmem_aw_status==STATUS_INIT)begin
            HP0_awvalid <= 1;
            write1_time <= 0;
            if(HP0_awready)begin
              debug_readmem_aw_status <= STATUS_FINISH;
            end else begin
              debug_readmem_aw_status <= STATUS_WAIT;
            end
          end else if(debug_readmem_aw_status==STATUS_WAIT)begin
            write1_time <= write1_time + 1'b1;
            if(HP0_awready)begin
              debug_readmem_aw_status <= STATUS_FINISH;
            end
          end else if(debug_readmem_aw_status==STATUS_FINISH)begin
            HP0_awvalid <= 0;
          end
          
          if         (debug_readmem_dw_status==STATUS_INIT)begin
            HP0_wvalid <= 1;
            HP0_wlast <= 1;
            write2_time <= 0;
            if(HP0_wready)begin
              debug_readmem_dw_status <= STATUS_FINISH;
            end else begin
              debug_readmem_dw_status <= STATUS_WAIT;
            end
          end else if(debug_readmem_dw_status==STATUS_WAIT)begin
            write2_time <= write2_time + 1'b1;
            if(HP0_wready)begin
              debug_readmem_dw_status <= STATUS_FINISH;
            end
          end else if(debug_readmem_dw_status==STATUS_FINISH)begin
            HP0_wvalid <= 0;
            HP0_wlast <= 0;
          end
   
          if         (debug_readmem_b_status==STATUS_INIT)begin
            HP0_bready <= 1;
            write3_time <= 0;
            if(HP0_bvalid)begin
              debug_readmem_b_status <= STATUS_FINISH;
            end else begin
              debug_readmem_b_status <= STATUS_WAIT;
            end
          end else if(debug_readmem_b_status==STATUS_WAIT)begin
            write3_time <= write3_time + 1'b1;
            if(HP0_bvalid)begin
              debug_readmem_b_status <= STATUS_FINISH;
            end
          end else if(debug_readmem_b_status==STATUS_FINISH)begin
            HP0_bready <= 0;
          end

          if(debug_readmem_aw_status == STATUS_FINISH && debug_readmem_dw_status==STATUS_FINISH && debug_readmem_b_status==STATUS_FINISH)begin
            command_ack = 1;
            debug_data_send<=1; debug_data_out <= 8'h34;
            debug_readmem_aw_status <= STATUS_INIT;
            debug_readmem_dw_status <= STATUS_INIT;
            debug_readmem_b_status <= STATUS_INIT;
          end

        end
`endif

        
        8'h10 : begin halt_debug<=1'b0; command_ack<=1; end //HALT_DEBUG0
        8'h11 : begin halt_debug<=1'b1; command_ack<=1; end //HALT_DEBUG1
        8'h12 : begin debug_reset_n<=1'b0; command_ack<=1; end //DEBUG_RESET_N0
        8'h13 : begin debug_reset_n<=1'b1; command_ack<=1; end //DEBUG_RESET_N1
        8'h14 : begin debug_step<=~debug_step; command_ack<=1; end //DEBUG_STEP
        8'h15 : begin debug_byteenable <= data[3:0]; command_ack<=1; end//SET_BYTE_ENABLE
        8'h16 : begin debug_address <= data; command_ack<=1; end//SET_DEBUG_ADDRESS
        8'h17 : begin debug_writedata <= data; command_ack<=1; end//SET_DEBUG_WRITEDATA
        8'h18 : begin debug_vga_base_addr<= data; command_ack<=1; end // SET_DEBUG_VGA_BASE_ADDR
        8'h19 : begin debug_flg <= data[0]; command_ack<=1; end //SET_DEBUG_FLG
        8'h1A : begin debug_hid <= data; command_ack<=1; end //SET_DEBUG_HID
        8'h1B : begin debug_hid_req <= data[0]; command_ack<=1; end //SET_DEBUG_HID_REQ
        8'h1C : begin debug_data_send<=1; debug_data_out<=data; command_ack<=1; end //GET_ECHO
        8'h1D : begin debug_data_send<=1; debug_data_out<=32'h12345678; command_ack<=1; end //GET_CONST_ECHO
        
        8'h20 : begin debug_data_send<=1; debug_data_out<=debugin8; command_ack<=1; end //GET_DEBUG8
        8'h21 : begin debug_data_send<=1; debug_data_out<=debugin32; command_ack<=1; end // GET_DEBUG32
        8'h22 : begin debug_data_send<=1; debug_data_out<=accessTime; command_ack<=1; end //GET_ACCESS_TIME
        8'h23 : begin debug_data_send<=1; debug_data_out<=avm_m0_address; command_ack<=1; end //GET_AVM_M0_ADDRESS
        8'h24 : begin debug_data_send<=1; debug_data_out<=private_offset_rear; command_ack<=1; end //GET_PRIVATE_OFFSET_REAR
        8'h25 : begin debug_data_send<=1; debug_data_out<=pc_record_data; command_ack<=1; end //GET_PC_RECORD_DATA
        8'h26 : begin debug_data_send<=1; debug_data_out<=pc_record_index; command_ack<=1; end //GET_PC_RECORD_INDEX
        8'h27 : begin debug_data_send<=1; debug_data_out<={avm_m1_waitrequest,halt_cpu,halt_debug,avm_m0_waitrequest,irq_enable,irq_req}; command_ack<=1; end //GET_MISC

        8'h28 : begin debug_data_send<=1; debug_data_out<=irq_addr; command_ack<=1; end //GET_IRQ_ADDR
        8'h29 : begin debug_data_send<=1; debug_data_out<=cpu_address; command_ack<=1; end //GET_CPU_ADDRESS
        8'h2A : begin debug_data_send<=1; debug_data_out<=pc; command_ack<=1; end // GET_PC
        8'h2B : begin debug_data_send<=1; debug_data_out<=private_offset; command_ack<=1; end //GET_PRIVATE_OFFSET
        8'h2C : begin debug_data_send<=1; debug_data_out<=pcResult; command_ack<=1; end //GET_PC_RESULT
        8'h2D : begin debug_data_send<=1; debug_data_out<=curr_data; command_ack<=1; end //GET_CURR_DATA

        8'h2E : begin debug_data_send<=1; debug_data_out<=debug_stash_data; command_ack<=1; end //  GET_DEBUG_STASH_DATA
        8'h2F : begin debug_data_send<=1; debug_data_out<=debug_stash_index; command_ack<=1; end // GET_DEBUG_STASH_INDEX

        //mem read
        8'h30 : begin//MEM_READ
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            debug_read <= 1;
          end else if(debug_readmem_step==1)begin
            if(!avm_m0_waitrequest)begin
              debug_data_out <= avm_m0_readdata;
              debug_read <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end

        //mem_write
        8'h31 : begin//MEM_WRITE
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            debug_write <= 1;
          end else if(debug_readmem_step==1)begin
            if(!avm_m0_waitrequest)begin
              debug_data_out<=123;
              debug_write <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end

        //ins read
        8'h32 : begin //INS_READ
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            debug_read_ins <= 1;
          end else if(debug_readmem_step==1)begin
            if(!avm_m1_waitrequest)begin
              debug_data_out <= avm_m1_readdata;
              debug_read_ins <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1;
              command_ack <= 1;
            end
          end
        end

        //内存批量 len = data, start = debug_address
        8'h34 : begin//MEM_TRANS_READ
          case(debug_memcpy_step)
          0:begin
            debug_address<=data;
            debug_memcpy_step <= 3;
            //debug_read <= 1;
          end
          1:begin
            if(!avm_m0_waitrequest)begin
              debug_read <= 0;
              debug_regWriteEna_reg <= 1;
              debug_writedata <= avm_m0_readdata;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            debug_regWriteEna_reg <= 0;
            debug_memcpy_step <= 3;
            debug_address[31:2] <= debug_address[31:2] + 1'b1;
          end
          3:begin
            if(debug_address==data+2048)begin
              debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
              debug_memcpy_step <= 0;
            end else begin
              debug_memcpy_step <= 1;
              debug_read <= 1;
            end
          end
          endcase
        end

        8'h35 : begin //MEM_TRANS_WRITE
          case(debug_memcpy_step)
          0:begin
            debug_address<=data;
            //debug_writedata <= debug_regData;
            debug_memcpy_step <= 2;
            //debug_write <= 1;
          end
          1:begin
            if(!avm_m0_waitrequest)begin
              debug_write <= 0;
              debug_address[31:2] <= debug_address[31:2] + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            debug_memcpy_step <= 3;
          end
          3:begin
            if(debug_address==data+2048)begin
              debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
              debug_memcpy_step <= 0;
            end else begin
              debug_writedata <= debug_regData;
              debug_memcpy_step <= 1;
              debug_write <= 1;
            end
          end
          endcase
        end

        //reg read
        8'h37 : begin//REG_READ
          //assign debug_regAddr = debug_address[8:0]; //assign debug_regWriteData = debug_writedata;
          debug_data_send<=1;
          debug_data_out <= debug_regData;
          command_ack <= 1;
        end

        //reg write
        8'h38 : begin//REG_WRITE
          //assign debug_regAddr = debug_address[8:0]; //assign debug_regWriteData = debug_writedata;
          if(debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            debug_regWriteEna_reg <= 1;
          end else begin
            debug_data_send<=1;
            debug_data_out<=123;
            debug_readmem_step <= 0;
            debug_regWriteEna_reg <= 0;
            command_ack <= 1;
          end
        end

        8'h40 : begin//DEBUG_TX_TO_PC
          debug_tx_to_pc_read <= 1;
          debug_data_send<=1;
          debug_data_out<=debug_tx_to_pc;
          command_ack<=1;
        end
        8'h41 : begin//DEBUG_TX_STATUS_TO_PC
          debug_data_send<=1;
          debug_data_out<=debug_tx_to_pc_valid;
          command_ack<=1;
        end
        8'h42 : begin//DEBUG_RX_FROM_PC
          if(debug_rx_from_pc_valid)begin
            debug_data_send<=1;
            debug_data_out<=0;
          end else begin
            debug_data_send<=1;
            debug_data_out<=1;
            debug_rx_from_pc <= data;
            debug_rx_from_pc_valid <= 1;
          end
          command_ack<=1;
        end

        8'h50 : begin vga_control_by_debugger <= data[0]; command_ack<=1; end//VGA_CONTROL_BY_DEBUGGER
        8'h51 : begin vga_debugger_read_line_addr <= data[15:0]; command_ack<=1; end//VGA_DEBUGGER_READ_LINE_ADDR
        8'h52 : begin//VGA_DEBUGGER_READ_LINE_REQ
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            vga_debugger_read_line_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(vga_debugger_read_line_ack_buff)begin
              debug_data_out<=123;
              debug_data_send<=1;
              debug_readmem_step <= 0;
              vga_debugger_read_line_req <= 0;
              command_ack <= 1;
            end
          end
        end

  
        8'h60 : begin cache_debug_index <= data[4:0]; command_ack<=1; end //SET_CACHE_DEBUG_INDEX

        8'h62 : begin debug_nocache <= 1'b0; command_ack<=1; end //NOCACHE0
        8'h63 : begin debug_nocache <= 1'b1; command_ack<=1; end //NOCACHE1

        8'h64 : begin debug_data_send<=1; debug_data_out<=free_cache_timer; command_ack<=1; end //GET_CACHE_LIFE_COUNT
        8'h65 : begin debug_data_send<=1; debug_data_out<=flushCount; command_ack<=1; end//GET_FLUSH_COUNT
        8'h68 : begin debug_data_send<=1; debug_data_out<=glichCount; command_ack<=1; end//GET_GLICH_COUNT
        8'h69 : begin debug_data_send<=1; debug_data_out<=glichCountIns; command_ack<=1; end//GET_GLICH_COUNT_INS

        8'h61 : begin debug_data_send<=1; debug_data_out<=cache_debug_data; command_ack<=1; end //GET_CACHE_DEBUG_DATA
        8'h66 : begin debug_data_send<=1; debug_data_out<=cache_debugIns_data; command_ack<=1; end //GET_INS_CACHE_DEBUG_DATA
        
        8'h67 : begin debug_data_send<=1; debug_data_out<=cache_config; command_ack<=1; end//GET_CACHE_CONFIG
        
        
        8'h70 : begin spirom_debug_cs <= 1'b0; command_ack<=1; end //SPIROM_DEBUG_CS0
        8'h71 : begin spirom_debug_cs <= 1'b1; command_ack<=1; end //SPIROM_DEBUG_CS1
        8'h72 : begin //SPIROM_REC
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            spirom_debug_read_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(spirom_debug_read_ack_buff)begin
              spirom_debug_read_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1; debug_data_out<=spirom_debug_read_data; command_ack <= 1;
            end
          end
        end
        8'h73 : begin //SPIROM_SND
          if         (debug_readmem_step==0)begin
            debug_readmem_step <= 1;
            spirom_debug_write_data <= data[7:0];
            spirom_debug_write_req <= 1;
          end else if(debug_readmem_step==1)begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_readmem_step <= 0;
              debug_data_send<=1; debug_data_out<=123; command_ack <= 1;
            end
          end
        end
        8'h74 : begin //SPIROM_SND4
          case(debug_memcpy_step)
          0:begin
            //debug_address is zero
            case(debug_spirom_send4_index[1:0])
            0:spirom_debug_write_data <= data[7:0];
            1:spirom_debug_write_data <= data[15:8];
            2:spirom_debug_write_data <= data[23:16];
            3:spirom_debug_write_data <= data[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_memcpy_step <= 1;
          end
          1:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_spirom_send4_index <= debug_spirom_send4_index + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_memcpy_step <= 3;
            end
          end
          3:begin
            if(debug_spirom_send4_index==4)begin
              debug_spirom_send4_index <= 0;
              debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
            end
            debug_memcpy_step <= 0;
          end
          endcase
        end
        
        //spirom 批量
                //内存批量 len = data start = debug_address
        8'h76 : begin //SPIROM_TRANS_WRITE
          case(debug_memcpy_step)
          0:begin
            //debug_address is zero
            case(debug_address[1:0])
            0:spirom_debug_write_data <= debug_regData[7:0];
            1:spirom_debug_write_data <= debug_regData[15:8];
            2:spirom_debug_write_data <= debug_regData[23:16];
            3:spirom_debug_write_data <= debug_regData[31:24];
            endcase
            spirom_debug_write_req <= 1;
            debug_memcpy_step <= 1;
          end
          1:begin
            if(spirom_debug_write_ack_buff)begin
              spirom_debug_write_req <= 0;
              debug_address <= debug_address + 1'b1;
              debug_memcpy_step <= 2;
            end
          end
          2:begin
            if(!spirom_debug_write_ack_buff)begin
              debug_memcpy_step <= 3;
            end
          end
          3:begin
            if(debug_address==data)begin
              debug_data_out<=123;
              debug_data_send<=1;
              command_ack <= 1;
            end
            debug_memcpy_step <= 0;
          end
          endcase
        end

        
        default: begin
          command_ack<=1;
        end
        endcase
        
        if(accessTime[31:20])begin//accessTime > 1000000
          debug_read <= 0;
          debug_write <= 0;
          debug_read_ins <= 0;
          debug_memcpy_step <= 0;
          debug_readmem_step <= 0;
          debug_regWriteEna_reg <= 0;
          spirom_debug_read_req <= 0;
          spirom_debug_write_req <= 0;
          debug_data_send<=1; debug_data_out<=99; command_ack <= 1;
        end
      end

      if(!command_req && command_ack) begin//command_ack==0
        command_ack <= 0;
      end
      
      if(!debug_tx_to_pc_valid && debug_tx_to_pc_read)begin
        debug_tx_to_pc_read <= 0;
      end
      
      if(debug_rx_from_pc_read && debug_rx_from_pc_valid)begin
        debug_rx_from_pc_valid <= 0;
      end

    end
  end

endmodule

